/* Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "zobjects_stdtypes.h"

#define ZLANG_ARRAY_SIZE_DEFAULT	4
#define ZLANG_ARRAY_INCEASE_SIZE	64

struct ZlangDirectProperty_array
{
	struct ZlangObject		**array ;
	int32_t				array_size ;
	int32_t				array_length ;
} ;

static int InitArray( struct ZlangRuntime *rt , struct ZlangObject *obj )
{
	struct ZlangDirectProperty_array	*array_direct_prop = GetObjectDirectProperty(obj) ;
	
	array_direct_prop->array = (struct ZlangObject **)ZLMALLOC( sizeof(struct ZlangObject *) * ZLANG_ARRAY_SIZE_DEFAULT ) ;
	if( array_direct_prop->array == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_ALLOC , "alloc memory for array.array" )
		return ZLANG_ERROR_ALLOC;
	}
	memset( array_direct_prop->array , 0x00 , sizeof(struct ZlangObject *) * ZLANG_ARRAY_SIZE_DEFAULT );
	array_direct_prop->array_size = ZLANG_ARRAY_SIZE_DEFAULT ;
	array_direct_prop->array_length = 0 ;
	
	return 0;
}

static int TryIncreaseArray( struct ZlangRuntime *rt , struct ZlangObject *array_obj , struct ZlangDirectProperty_array *array_direct_prop )
{
	if( array_direct_prop->array_length >= array_direct_prop->array_size )
	{
		void		*new_array = NULL ;
		
		new_array = (struct ZlangObject **)ZLREALLOC( array_direct_prop->array , sizeof(struct ZlangObject *) * ( array_direct_prop->array_size + ZLANG_ARRAY_INCEASE_SIZE ) ) ;
		if( new_array == NULL )
		{
			SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_ALLOC , "ZLREALLOC memory for array.array" )
			return ZLANG_ERROR_ALLOC;
		}
		array_direct_prop->array = new_array ;
		array_direct_prop->array_size += ZLANG_ARRAY_INCEASE_SIZE ;
	}
	
	return 0;
}

ZlangDirectFunction_array_Append array_Append;
int array_Append( struct ZlangRuntime *rt , struct ZlangObject *obj , struct ZlangObject *element , struct ZlangObject **append )
{
	struct ZlangDirectProperty_array	*array_direct_prop = GetObjectDirectProperty(obj) ;
	char					*ext_obj_name = NULL ;
	char					*type_name = NULL ;
	struct ZlangObject			*new_element = NULL ;
	int					nret = 0 ;
	
	if( ! IsTypeOf( rt , obj , GetArrayObjectInRuntimeObjectsHeap(rt) ) )
		return ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED;
	
	IF_ATOMIC_OBJECT_THEN_LOCK( obj )
	
	if( array_direct_prop->array == NULL )
	{
		nret = InitArray( rt , obj ) ;
		if( nret )
		{
			IF_ATOMIC_OBJECT_THEN_UNLOCK( obj );
			return nret;
		}
	}
	
	ext_obj_name = GetObjectEmbellishName( obj ) ;
	type_name = GetCloneObjectName( element ) ;
	if( ext_obj_name )
	{
		if( type_name == NULL || STRCMP( ext_obj_name , != , type_name ) )
		{
			TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "object type not matched" )
			IF_ATOMIC_OBJECT_THEN_UNLOCK( obj );
			return -ZLANG_ERROR_TYPE_OF_OBJECT_NOT_MATCHED;
		}
	}
	
	new_element = AllocObject( rt ) ;
	if( new_element == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_ALLOC , "alloc memory for object" )
		IF_ATOMIC_OBJECT_THEN_UNLOCK( obj );
		return ZLANG_ERROR_ALLOC;
	}
	
	nret = ReferObject( rt , new_element , element ) ;
	if( nret )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "ReferObject failed[%d]" , nret )
		DestroyObject( rt , new_element );
		IF_ATOMIC_OBJECT_THEN_UNLOCK( obj );
		return nret;
	}
	
	nret = SetObjectName( rt , new_element , GetObjectName(element) ) ;
	if( nret )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "SetObjectName failed[%d]" , nret )
		DestroyObject( rt , new_element );
		IF_ATOMIC_OBJECT_THEN_UNLOCK( obj );
		return nret;
	}
	
	array_direct_prop->array[array_direct_prop->array_length] = new_element ;
	array_direct_prop->array_length++;
	
	nret = TryIncreaseArray( rt , obj , array_direct_prop ) ;
	
	if( append )
		(*append) = new_element ;
	IF_ATOMIC_OBJECT_THEN_UNLOCK( obj );
	return nret;
}

ZlangInvokeFunction ZlangInvokeFunction_array_Append_object;
int ZlangInvokeFunction_array_Append_object( struct ZlangRuntime *rt , struct ZlangObject *obj )
{
	struct ZlangObject	*in1 = GetInputParameterInLocalObjectStack(rt,1) ;
	struct ZlangObject	*out1 = GetOutputParameterInLocalObjectStack(rt,1) ;
	struct ZlangObject	*append = NULL ;
	int			nret = 0 ;
	
	nret = array_Append( rt , obj , in1 , & append ) ;
	if( nret )
	{
		UnreferObject( rt , out1 );
		if( nret < 0 )
			return ThrowFatalException( rt , nret , EXCEPTION_MESSAGE_APPEND_ARRAY_FAILED );
		else
			return ThrowErrorException( rt , EXCEPTION_CODE_GENERAL , EXCEPTION_MESSAGE_APPEND_ARRAY_FAILED );
	}
	
	nret = ReferObject( rt , out1 , append ) ;
	if( nret )
	{
		UnreferObject( rt , out1 );
		return ThrowFatalException( rt , nret , EXCEPTION_MESSAGE_REFER_OBJECT_FAILED );
	}
	
	return 0;
}

ZlangDirectFunction_array_InsertBefore array_InsertBefore;
int array_InsertBefore( struct ZlangRuntime *rt , struct ZlangObject *obj , int32_t element_no , struct ZlangObject *element , struct ZlangObject **insert )
{
	struct ZlangDirectProperty_array	*array_direct_prop = GetObjectDirectProperty(obj) ;
	char					*ext_obj_name = NULL ;
	char					*type_name = NULL ;
	struct ZlangObject			*new_element = NULL ;
	int					nret = 0 ;
	
	if( ! IsTypeOf( rt , obj , GetArrayObjectInRuntimeObjectsHeap(rt) ) )
		return ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED;
	
	IF_ATOMIC_OBJECT_THEN_LOCK( obj )
	
	if( element_no < 1 || element_no > array_direct_prop->array_length )
	{
		IF_ATOMIC_OBJECT_THEN_UNLOCK( obj );
		return ZLANG_ERROR_PARAMETER;
	}
	
	if( array_direct_prop->array == NULL )
	{
		nret = InitArray( rt , obj ) ;
		if( nret )
		{
			IF_ATOMIC_OBJECT_THEN_UNLOCK( obj );
			return nret;
		}
	}
	
	ext_obj_name = GetObjectEmbellishName( obj ) ;
	type_name = GetCloneObjectName( element ) ;
	if( ext_obj_name )
	{
		if( type_name == NULL || STRCMP( ext_obj_name , != , type_name ) )
		{
			TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "object type not matched" )
			IF_ATOMIC_OBJECT_THEN_UNLOCK( obj );
			return -ZLANG_ERROR_TYPE_OF_OBJECT_NOT_MATCHED;
		}
	}
	
	new_element = AllocObject( rt ) ;
	if( new_element == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_ALLOC , "alloc memory for object" )
		IF_ATOMIC_OBJECT_THEN_UNLOCK( obj );
		return ZLANG_ERROR_ALLOC;
	}
	
	nret = ReferObject( rt , new_element , element ) ;
	if( nret )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "ReferObject failed[%d]" , nret )
		DestroyObject( rt , new_element );
		IF_ATOMIC_OBJECT_THEN_UNLOCK( obj );
		return nret;
	}
	
	nret = SetObjectName( rt , new_element , GetObjectName(element) ) ;
	if( nret )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "SetObjectName failed[%d]" , nret )
		DestroyObject( rt , new_element );
		IF_ATOMIC_OBJECT_THEN_UNLOCK( obj );
		return nret;
	}
	
	memmove( array_direct_prop->array+element_no , array_direct_prop->array+element_no-1 , sizeof(struct ZlangObject *)*array_direct_prop->array_length-(element_no-1) );
	array_direct_prop->array[element_no-1] = new_element ;
	array_direct_prop->array_length++;
	
	nret = TryIncreaseArray( rt , obj , array_direct_prop ) ;
	
	if( insert )
		(*insert) = new_element ;
	IF_ATOMIC_OBJECT_THEN_UNLOCK( obj );
	return nret;
}

ZlangInvokeFunction ZlangInvokeFunction_array_InsertBefore_int_object;
int ZlangInvokeFunction_array_InsertBefore_int_object( struct ZlangRuntime *rt , struct ZlangObject *obj )
{
	struct ZlangObject	*in1 = GetInputParameterInLocalObjectStack(rt,1) ;
	struct ZlangObject	*in2 = GetInputParameterInLocalObjectStack(rt,2) ;
	struct ZlangObject	*out1 = GetOutputParameterInLocalObjectStack(rt,1) ;
	struct ZlangObject	*insert = NULL ;
	int32_t			element_no ;
	int			nret = 0 ;
	
	CallRuntimeFunction_int_GetIntValue( rt , in1 , & element_no );
	
	nret = array_InsertBefore( rt , obj , element_no , in2 , & insert ) ;
	if( nret )
	{
		UnreferObject( rt , out1 );
		if( nret < 0 )
			return ThrowFatalException( rt , nret , EXCEPTION_MESSAGE_INSERT_BEFORE_ARRAY_FAILED );
		else
			return ThrowErrorException( rt , EXCEPTION_CODE_GENERAL , EXCEPTION_MESSAGE_INSERT_BEFORE_ARRAY_FAILED );
	}
	
	nret = ReferObject( rt , out1 , insert ) ;
	if( nret )
	{
		UnreferObject( rt , out1 );
		return ThrowFatalException( rt , nret , EXCEPTION_MESSAGE_REFER_OBJECT_FAILED );
	}
	
	return 0;
}

ZlangDirectFunction_array_Remove array_Remove;
int array_Remove( struct ZlangRuntime *rt , struct ZlangObject *obj , int32_t element_no )
{
	struct ZlangDirectProperty_array	*array_direct_prop = GetObjectDirectProperty(obj) ;
	int					nret = 0 ;
	
	if( ! IsTypeOf( rt , obj , GetArrayObjectInRuntimeObjectsHeap(rt) ) )
		return ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED;
	
	IF_ATOMIC_OBJECT_THEN_LOCK( obj )
	
	if( element_no < 1 || element_no > array_direct_prop->array_length )
	{
		IF_ATOMIC_OBJECT_THEN_UNLOCK( obj );
		return ZLANG_ERROR_PARAMETER;
	}
	
	if( array_direct_prop->array == NULL )
	{
		nret = InitArray( rt , obj ) ;
		if( nret )
		{
			IF_ATOMIC_OBJECT_THEN_UNLOCK( obj );
			return nret;
		}
	}
	
	DestroyObject( rt , array_direct_prop->array[element_no-1] );
	memmove( array_direct_prop->array+element_no-1 , array_direct_prop->array+element_no , sizeof(struct ZlangObject *)*(array_direct_prop->array_length-element_no) );
	array_direct_prop->array[array_direct_prop->array_length-1] = NULL ;
	array_direct_prop->array_length--;
	
	IF_ATOMIC_OBJECT_THEN_UNLOCK( obj );
	
	return 0;
}

ZlangInvokeFunction ZlangInvokeFunction_array_Remove_object;
int ZlangInvokeFunction_array_Remove_object( struct ZlangRuntime *rt , struct ZlangObject *obj )
{
	struct ZlangObject	*in1 = GetInputParameterInLocalObjectStack(rt,1) ;
	int32_t			element_no ;
	int			nret = 0 ;
	
	CallRuntimeFunction_int_GetIntValue( rt , in1 , & element_no );
	
	nret = array_Remove( rt , obj , element_no ) ;
	if( nret )
		return ThrowErrorException( rt , nret , EXCEPTION_MESSAGE_GENERAL_ERROR );
	else
		return 0;
}

ZlangDirectFunction_array_RemoveAll array_RemoveAll;
int array_RemoveAll( struct ZlangRuntime *rt , struct ZlangObject *obj )
{
	struct ZlangDirectProperty_array	*array_direct_prop = GetObjectDirectProperty(obj) ;
	int32_t					element_no ;
	int					nret = 0 ;
	
	if( ! IsTypeOf( rt , obj , GetArrayObjectInRuntimeObjectsHeap(rt) ) )
		return ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED;
	
	IF_ATOMIC_OBJECT_THEN_LOCK( obj )
	
	for( element_no = 1 ; element_no <= array_direct_prop->array_length ; element_no++ )
	{
		DestroyObject( rt , array_direct_prop->array[element_no-1] );
		array_direct_prop->array[element_no-1] = NULL ;
	}
	array_direct_prop->array_length = 0 ;
	
	IF_ATOMIC_OBJECT_THEN_UNLOCK( obj );
	
	return 0;
}

ZlangInvokeFunction ZlangInvokeFunction_array_RemoveAll;
int ZlangInvokeFunction_array_RemoveAll( struct ZlangRuntime *rt , struct ZlangObject *obj )
{
	int		nret = 0 ;
	
	nret = array_RemoveAll( rt , obj ) ;
	if( nret )
		return ThrowErrorException( rt , nret , EXCEPTION_MESSAGE_GENERAL_ERROR );
	else
		return 0;
}

ZlangDirectFunction_array_Get array_Get;
int array_Get( struct ZlangRuntime *rt , struct ZlangObject *obj , int32_t element_no , struct ZlangObject **element )
{
	struct ZlangDirectProperty_array	*array_direct_prop = GetObjectDirectProperty(obj) ;
	int					nret = 0 ;
	
	if( ! IsTypeOf( rt , obj , GetArrayObjectInRuntimeObjectsHeap(rt) ) )
		return ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED;
	
	IF_ATOMIC_OBJECT_THEN_LOCK( obj )
	
	if( element )
	{
		if( element_no < 1 || element_no > array_direct_prop->array_length )
			(*element) = NULL ;
		else
			(*element) = array_direct_prop->array[element_no-1] ;
	}
	
	IF_ATOMIC_OBJECT_THEN_UNLOCK( obj );
	
	return 0;
}

ZlangInvokeFunction ZlangInvokeFunction_array_Get_int;
int ZlangInvokeFunction_array_Get_int( struct ZlangRuntime *rt , struct ZlangObject *obj )
{
	struct ZlangObject	*in1 = GetInputParameterInLocalObjectStack(rt,1) ;
	struct ZlangObject	*out1 = GetOutputParameterInLocalObjectStack(rt,1) ;
	int32_t			element_no ;
	struct ZlangObject	*element = NULL ;
	int			nret = 0 ;
	
	CallRuntimeFunction_int_GetIntValue( rt , in1 , & element_no );
	nret = array_Get( rt , obj , element_no , & element ) ;
	if( nret )
		return ThrowErrorException( rt , nret , EXCEPTION_MESSAGE_GENERAL_ERROR );
	
	if( element )
		nret = ReferObject( rt , out1 , element ) ;
	else
		nret = UnreferObject( rt , out1 ) ;
	if( nret )
		return ThrowErrorException( rt , nret , EXCEPTION_MESSAGE_GENERAL_ERROR );
	
	return 0;
}

ZlangDirectFunction_array_Set array_Set;
int array_Set( struct ZlangRuntime *rt , struct ZlangObject *obj , int32_t element_no , struct ZlangObject *element )
{
	struct ZlangDirectProperty_array	*array_direct_prop = GetObjectDirectProperty(obj) ;
	int					nret = 0 ;
	
	if( ! IsTypeOf( rt , obj , GetArrayObjectInRuntimeObjectsHeap(rt) ) )
		return ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED;
	
	IF_ATOMIC_OBJECT_THEN_LOCK( obj )
	
	if( element_no < 1 || element_no > array_direct_prop->array_length )
	{
		IF_ATOMIC_OBJECT_THEN_UNLOCK( obj );
		return ZLANG_ERROR_PARAMETER;
	}
	
	nret = ReferObject( rt , array_direct_prop->array[element_no-1] , element ) ;
	if( nret )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "ReferObject failed[%d]" , nret )
		IF_ATOMIC_OBJECT_THEN_UNLOCK( obj );
		return nret;
	}
	
	nret = SetObjectName( rt , array_direct_prop->array[element_no-1] , GetObjectName(element) ) ;
	if( nret )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "SetObjectName failed[%d]" , nret )
		IF_ATOMIC_OBJECT_THEN_UNLOCK( obj );
		return nret;
	}
	
	IF_ATOMIC_OBJECT_THEN_UNLOCK( obj );
	
	return 0;
}

ZlangInvokeFunction ZlangInvokeFunction_array_Set_int;
int ZlangInvokeFunction_array_Set_int( struct ZlangRuntime *rt , struct ZlangObject *obj )
{
	struct ZlangObject	*in1 = GetInputParameterInLocalObjectStack(rt,1) ;
	struct ZlangObject	*in2 = GetInputParameterInLocalObjectStack(rt,2) ;
	struct ZlangObject	*out1 = GetOutputParameterInLocalObjectStack(rt,1) ;
	int32_t			element_no ;
	int			nret = 0 ;
	
	CallRuntimeFunction_int_GetIntValue( rt , in1 , & element_no );
	nret = array_Set( rt , obj , element_no , in2 ) ;
	if( nret )
	{
		CallRuntimeFunction_bool_SetBoolValue( rt , out1 , FALSE );
		return ThrowErrorException( rt , nret , EXCEPTION_MESSAGE_GENERAL_ERROR );
	}
	
	CallRuntimeFunction_bool_SetBoolValue( rt , out1 , TRUE );
	return 0;
}

ZlangDirectFunction_array_Length array_Length;
int array_Length( struct ZlangRuntime *rt , struct ZlangObject *obj , int32_t *array_length )
{
	struct ZlangDirectProperty_array	*array_direct_prop = GetObjectDirectProperty(obj) ;
	int32_t					a_length ;
	int					nret = 0 ;
	
	if( ! IsTypeOf( rt , obj , GetArrayObjectInRuntimeObjectsHeap(rt) ) )
		return ZLANG_ERROR_FUNC_PARAMETER_TYPE_NOT_MATCHED;
	
	IF_ATOMIC_OBJECT_THEN_LOCK( obj )
	
	if( array_direct_prop == NULL )
		a_length = 0 ;
	else
		a_length = array_direct_prop->array_length ;
	
	if( array_length )
		(*array_length) = a_length ;
	IF_ATOMIC_OBJECT_THEN_UNLOCK( obj );
	return 0;
}

ZlangInvokeFunction ZlangInvokeFunction_array_Length;
int ZlangInvokeFunction_array_Length( struct ZlangRuntime *rt , struct ZlangObject *obj )
{
	int32_t			length ;
	struct ZlangObject	*out1 = GetOutputParameterInLocalObjectStack(rt,1) ;
	
	array_Length( rt , obj , & length );
	CallRuntimeFunction_int_SetIntValue( rt , out1 , length );
	
	return 0;
}

ZlangInvokeFunction ZlangInvokeFunction_array_IsEmpty;
int ZlangInvokeFunction_array_IsEmpty( struct ZlangRuntime *rt , struct ZlangObject *obj )
{
	struct ZlangDirectProperty_array	*array_direct_prop = GetObjectDirectProperty(obj) ;
	struct ZlangObject			*out1 = GetOutputParameterInLocalObjectStack(rt,1) ;
	unsigned char				b ;
	int					nret = 0 ;
	
	IF_ATOMIC_OBJECT_THEN_LOCK( obj )
	
	if( array_direct_prop->array_length == 0 )
		b = TRUE ;
	else
		b = FALSE ;
	CallRuntimeFunction_bool_SetBoolValue( rt , out1 , b );
	
	IF_ATOMIC_OBJECT_THEN_UNLOCK( obj );
	
	return 0;
}

ZlangInvokeFunction ZlangInvokeFunction_array_IsNotEmpty;
int ZlangInvokeFunction_array_IsNotEmpty( struct ZlangRuntime *rt , struct ZlangObject *obj )
{
	struct ZlangDirectProperty_array	*array_direct_prop = GetObjectDirectProperty(obj) ;
	struct ZlangObject			*out1 = GetOutputParameterInLocalObjectStack(rt,1) ;
	unsigned char				b ;
	int					nret = 0 ;
	
	IF_ATOMIC_OBJECT_THEN_LOCK( obj )
	
	if( array_direct_prop->array_length > 0 )
		b = TRUE ;
	else
		b = FALSE ;
	CallRuntimeFunction_bool_SetBoolValue( rt , out1 , b );
	
	IF_ATOMIC_OBJECT_THEN_UNLOCK( obj );
	
	return 0;
}

ZlangCreateDirectPropertyFunction ZlangCreateDirectProperty_array;
void *ZlangCreateDirectProperty_array( struct ZlangRuntime *rt , struct ZlangObject *obj )
{
	struct ZlangDirectProperty_array	*array_direct_prop = NULL ;
	
	array_direct_prop = (struct ZlangDirectProperty_array *)ZLMALLOC( sizeof(struct ZlangDirectProperty_array) ) ;
	if( array_direct_prop == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_ALLOC , "alloc memory for entity" )
		return NULL;
	}
	memset( array_direct_prop , 0x00 , sizeof(struct ZlangDirectProperty_array) );
	
	return (struct ZlangEntity *)array_direct_prop;
}

ZlangDestroyDirectPropertyFunction ZlangDestroyDirectProperty_array;
void ZlangDestroyDirectProperty_array( struct ZlangRuntime *rt , struct ZlangObject *obj )
{
	struct ZlangDirectProperty_array	*array_direct_prop = GetObjectDirectProperty(obj) ;
	int32_t					element_no ;
	struct ZlangObject			**element = NULL ;
	
	for( element_no = 0 , element = array_direct_prop->array ; element_no < array_direct_prop->array_length ; element_no++ , element++ )
	{
		DestroyObject( rt , (*element) );
	}
	
	ZLFREE( array_direct_prop->array );
	ZLFREE( array_direct_prop );
	
	return;
}

ZlangSummarizeDirectPropertySizeFunction ZlangSummarizeDirectPropertySize_array;
void ZlangSummarizeDirectPropertySize_array( struct ZlangRuntime *rt , struct ZlangObject *obj , size_t *summarized_obj_size , size_t *summarized_direct_prop_size )
{
	struct ZlangDirectProperty_array	*array_direct_prop = GetObjectDirectProperty(obj) ;
	int32_t					element_no ;
	
	for( element_no = 1 ; element_no <= array_direct_prop->array_length ; element_no++ )
	{
		SummarizeObjectSize( rt , array_direct_prop->array[element_no-1] , summarized_obj_size , summarized_direct_prop_size );
	}
	
	SUMMARIZE_SIZE( summarized_direct_prop_size , sizeof(struct ZlangDirectProperty_array) )
	
	return;
}

static struct ZlangDirectFunctions direct_funcs_array =
	{
		ZLANG_OBJECT_array ,
		
		ZlangCreateDirectProperty_array ,
		ZlangDestroyDirectProperty_array ,
		
		NULL ,
		NULL ,
		NULL ,
		NULL ,
		
		NULL ,
		NULL ,
		NULL ,
		NULL ,
		NULL ,
		
		NULL ,
		NULL ,
		NULL ,
		NULL ,
		NULL ,
		
		NULL ,
		NULL ,
		NULL ,
		NULL ,
		NULL ,
		NULL ,
		
		NULL ,
		NULL ,
		
		NULL ,
		NULL ,
		NULL ,
		NULL ,
		NULL ,
		
		ZlangSummarizeDirectPropertySize_array ,
	} ;

ZlangImportObjectFunction ZlangImportObject_array;
struct ZlangObject *ZlangImportObject_array( struct ZlangRuntime *rt )
{
	struct ZlangObject	*obj = NULL ;
	struct ZlangFunction	*func = NULL ;
	int			nret = 0 ;
	
	nret = ImportObject( rt , & obj , ZLANG_OBJECT_array , & direct_funcs_array , sizeof(struct ZlangDirectFunctions) , NULL ) ;
	if( nret )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_LINK_FUNC_TO_ENTITY , "import object to global objects heap" )
		DestroyObject( rt , obj );
		return NULL;
	}
	
	func = AddFunctionAndParametersInObject( rt , obj , ZlangInvokeFunction_array_Append_object , ZLANG_OBJECT_object , "Append" , ZLANG_OBJECT_object,NULL , NULL ) ;
	if( func == NULL )
		return NULL;
	
	func = AddFunctionAndParametersInObject( rt , obj , ZlangInvokeFunction_array_Append_object , ZLANG_OBJECT_object , "Append" , ZLANG_OBJECT_string,NULL , NULL ) ;
	if( func == NULL )
		return NULL;
	
	func = AddFunctionAndParametersInObject( rt , obj , ZlangInvokeFunction_array_Append_object , ZLANG_OBJECT_object , "Append" , ZLANG_OBJECT_int,NULL , NULL ) ;
	if( func == NULL )
		return NULL;
	
	func = AddFunctionAndParametersInObject( rt , obj , ZlangInvokeFunction_array_InsertBefore_int_object , ZLANG_OBJECT_object , "InsertBefore" , ZLANG_OBJECT_int,NULL , ZLANG_OBJECT_object,NULL , NULL ) ;
	if( func == NULL )
		return NULL;
	
	func = AddFunctionAndParametersInObject( rt , obj , ZlangInvokeFunction_array_InsertBefore_int_object , ZLANG_OBJECT_object , "InsertBefore" , ZLANG_OBJECT_int,NULL , ZLANG_OBJECT_string,NULL , NULL ) ;
	if( func == NULL )
		return NULL;
	
	func = AddFunctionAndParametersInObject( rt , obj , ZlangInvokeFunction_array_InsertBefore_int_object , ZLANG_OBJECT_object , "InsertBefore" , ZLANG_OBJECT_int,NULL , ZLANG_OBJECT_int,NULL , NULL ) ;
	if( func == NULL )
		return NULL;
	
	func = AddFunctionAndParametersInObject( rt , obj , ZlangInvokeFunction_array_Remove_object , ZLANG_OBJECT_void , "Remove" , ZLANG_OBJECT_int,NULL , NULL ) ;
	if( func == NULL )
		return NULL;
	
	func = AddFunctionAndParametersInObject( rt , obj , ZlangInvokeFunction_array_RemoveAll , ZLANG_OBJECT_void , "RemoveAll" , NULL ) ;
	if( func == NULL )
		return NULL;
	
	func = AddFunctionAndParametersInObject( rt , obj , ZlangInvokeFunction_array_Get_int , ZLANG_OBJECT_object , "Get" , ZLANG_OBJECT_int,NULL , NULL ) ;
	if( func == NULL )
		return NULL;
	
	func = AddFunctionAndParametersInObject( rt , obj , ZlangInvokeFunction_array_Set_int , ZLANG_OBJECT_bool , "Set" , ZLANG_OBJECT_int,NULL , ZLANG_OBJECT_object,NULL , NULL ) ;
	if( func == NULL )
		return NULL;
	
	func = AddFunctionAndParametersInObject( rt , obj , ZlangInvokeFunction_array_Length , ZLANG_OBJECT_int , "Length" , NULL ) ;
	if( func == NULL )
		return NULL;
	
	func = AddFunctionAndParametersInObject( rt , obj , ZlangInvokeFunction_array_IsEmpty , ZLANG_OBJECT_bool , "IsEmpty" , NULL ) ;
	if( func == NULL )
		return NULL;
	
	func = AddFunctionAndParametersInObject( rt , obj , ZlangInvokeFunction_array_IsNotEmpty , ZLANG_OBJECT_bool , "IsNotEmpty" , NULL ) ;
	if( func == NULL )
		return NULL;
	
	SetRuntimeFunction_array_Append( rt , array_Append );
	SetRuntimeFunction_array_InsertBefore( rt , array_InsertBefore );
	SetRuntimeFunction_array_Remove( rt , array_Remove );
	SetRuntimeFunction_array_RemoveAll( rt , array_RemoveAll );
	SetRuntimeFunction_array_Length( rt , array_Length );
	SetRuntimeFunction_array_Get( rt , array_Get );
	SetRuntimeFunction_array_Set( rt , array_Set );
	
	return obj ;
}

